package jmine.tec.utils.mail;

import java.util.Map;
import java.util.Properties;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;

import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.runtime.RuntimeConstants;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.ui.velocity.VelocityEngineUtils;

/**
 * Classe responsável pelo envio de emails.
 * 
 * @author Cesar Olmos
 */
public class MailRegister {
    private JavaMailSender mailSender;

    private String from;

    private VelocityEngine velocityEngine;

    private String encoding = "UTF-8";

    /**
     * Construtor
     * 
     * @throws MailException caso ocorra algum erro inicializando o sistema de emails
     */
    public MailRegister() throws MailException {
        this.velocityEngine = new VelocityEngine();
        Properties p = new Properties();
        p.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS, "org.apache.velocity.runtime.log.Log4JLogChute");
        p.setProperty("runtime.log.logsystem.log4j.logger", this.getClass().getName());
        p.setProperty("resource.loader", "class");
        p.setProperty("class.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
        try {
            this.velocityEngine.init(p);
        } catch (Exception e) {
            throw new MailException("Erro inicializando o serviço de envio de email.", e);
        }
    }

    /**
     * Define o mail sender que será utilizado.
     * 
     * @param mailSender o mail sender.
     */
    public void setMailSender(JavaMailSender mailSender) {
        this.mailSender = mailSender;
    }

    /**
     * Define o "from" dos emails enviados.
     * 
     * @param from o "from" dos emails enviados.
     */
    public void setFrom(String from) {
        this.from = from;
    }

    /**
     * Define o encoding.
     * 
     * @param encoding o encoding a ser definido.
     */
    public void setEncoding(String encoding) {
        this.encoding = encoding;
    }

    /**
     * Cria uma nova mensagem.
     * 
     * @return uma nova mensagem.
     */
    public MimeMessage createMimeMessage() {
        return this.mailSender.createMimeMessage();
    }

    /**
     * Envia uma mensagem.
     * 
     * @param message a mensagem.
     * @throws MailException caso ocorra algum erro no envio.
     */
    public void sendMessage(MimeMessage message) throws MailException {
        try {
            this.mailSender.send(message);
        } catch (org.springframework.mail.MailException e) {
            throw new MailException("Erro enviando mensagem.", e);
        }
    }

    /**
     * Envia uma mensagem.
     * 
     * @param to o detinatário.
     * @param subject o assunto.
     * @param content o conteúdo da mensagem.
     * @throws MailException caso ocorra algum erro no envio.
     */
    public void sendMessage(String to, String subject, String content) throws MailException {
        MimeMessage message = this.createMimeMessage();

        try {
            MimeMessageHelper helper = new MimeMessageHelper(message, true);
            helper.setFrom(this.from);
            helper.setTo(to);
            helper.setSubject(subject);
            helper.setText(content, true);
        } catch (MessagingException e) {
            throw new MailException("Erro enviando mensagem com assunto '" + subject + "'.", e);
        }

        this.sendMessage(message);
    }

    /**
     * Envia uma mensagem.
     * 
     * @param to o detinatário.
     * @param subject o assunto.
     * @param template o nome do template de email que será utilizado.
     * @param model o modelo que será utilizado para tradução do template.
     * @throws MailException caso ocorra algum erro no envio.
     */
    public void sendMessage(String to, String subject, String template, Map<String, Object> model) throws MailException {
        String content = VelocityEngineUtils.mergeTemplateIntoString(this.velocityEngine, template, this.encoding, model);
        this.sendMessage(to, subject, content);
    }
}
